home *** CD-ROM | disk | FTP | other *** search
/ CD Concept 6 / CD Concept 06.iso / mac / UTILITAIRE / Little Smalltalk v3.1.4 / C Source / Sources / lex.c < prev    next >
Text File  |  1994-07-23  |  6KB  |  269 lines

  1. /* 
  2.     Little Smalltalk, version 2
  3.     Written by Tim Budd, Oregon State University, July 1987
  4.  
  5.     lexical analysis routines for method parser
  6.     should be called only by parser 
  7. */
  8.  
  9. # include <stdio.h>
  10. # include <stdlib.h>
  11. # include <ctype.h>
  12. # ifdef LIGHTC
  13. # include <unix.h>
  14. # include <proto.h>
  15. # endif
  16. # include "env.h"
  17. # include "memory.h"
  18. # include "lex.h"
  19.  
  20. #ifdef THINKC
  21. # include "lex.proto.h"
  22. #else
  23.  static pushBack(char c);
  24.  static char nextChar(void);
  25.  static boolean isClosing(char c);
  26.  static boolean isSymbolChar(char c);
  27.  static boolean singleBinary(char c);
  28.  static boolean binarySecond(char c);
  29.  
  30.  static pushBack(char);
  31.  static char nextChar(void);
  32.  static boolean isClosing(char);
  33.  static boolean isSymbolChar(char);
  34.  static boolean singleBinary(char);
  35.  static boolean binarySecond(char);
  36. #endif
  37.  
  38. extern double atof();
  39.  
  40. /* global variables returned by lexical analyser */
  41.  
  42. tokentype token;        /* token variety */
  43. char tokenString[80];        /* text of current token */
  44. int tokenInteger;        /* integer (or character) value of token */
  45. double tokenFloat;        /* floating point value of token */
  46.  
  47. /* local variables used only by lexical analyser */
  48.  
  49. static char *cp;        /* character pointer */
  50. static char pushBuffer[10];    /* pushed back buffer */
  51. static int  pushindex;        /* index of last pushed back char */
  52. static char cc;            /* current character */
  53. static long longresult;        /* value used when building int tokens */
  54.  
  55. /* lexinit - initialize the lexical analysis routines */
  56. noreturn lexinit(char *str)
  57. {
  58.     pushindex = 0;
  59.     cp = str;
  60.     /* get first token */
  61.     ignore nextToken();
  62. }
  63.  
  64. /* pushBack - push one character back into the input */
  65. static void pushBack(char c)
  66. {
  67.     pushBuffer[pushindex++] = c;
  68. }
  69.  
  70. /* nextChar - retrieve the next char, from buffer or input */
  71. static char nextChar(void)
  72. {
  73.     if (pushindex > 0) cc = pushBuffer[--pushindex];
  74.     else if (*cp) cc = *cp++;
  75.     else cc = '\0';
  76.     return(cc);
  77. }
  78.  
  79. /* peek - take a peek at the next character */
  80. char peek(void)
  81. {
  82.     pushBack(nextChar());
  83.     return (cc);
  84. }
  85.  
  86. /* isClosing - characters which can close an expression */
  87. static boolean isClosing(char c)
  88. {
  89.     switch(c) {
  90.         case '.': case ']': case ')': case ';':
  91.         case '\"': case '\'':
  92.             return(true);
  93.     }
  94.     return(false);
  95. }
  96.  
  97. /* isSymbolChar - characters which can be part of symbols */
  98. static boolean isSymbolChar(char c)
  99. {
  100.     if (isdigit(c) || isalpha(c)) return(true);
  101.     if (isspace(c) || isClosing(c)) return(false);
  102.     return(true);
  103. }
  104.  
  105. /* singleBinary - binary characters that cannot be continued */
  106. static boolean singleBinary(char c)
  107. {
  108.     switch(c) {
  109.         case '[': case '(': case ')': case ']':
  110.             return(true);
  111.     }
  112.     return(false);
  113. }
  114.  
  115. /* binarySecond - return true if char can be second char in binary symbol */
  116. static boolean binarySecond(char c)
  117. {
  118.     if (isalpha(c) || isdigit(c) || isspace(c) || isClosing(c) ||
  119.         singleBinary(c))
  120.         return(false);
  121.     return(true);
  122. }
  123.  
  124. tokentype nextToken(void)
  125. {    char *tp;
  126.     boolean sign;
  127.  
  128.     /* skip over blanks and comments */
  129.     while(nextChar() && (isspace(cc) || (cc == '"')))
  130.         if (cc == '"') {
  131.             /* read comment */
  132.             while (nextChar() && (cc != '"')) ;
  133.             if (! cc) break;    /* break if we run into eof */
  134.             }
  135.  
  136.     tp = tokenString;
  137.     *tp++ = cc;
  138.  
  139.     if (! cc)            /* end of input */
  140.         token = inputend;
  141.     
  142.     else if (isalpha(cc)) {        /* identifier */
  143.         while (nextChar() && isalnum(cc))
  144.             *tp++ = cc;
  145.         if (cc == ':') {
  146.             *tp++ = cc;
  147.             token = namecolon;
  148.             }
  149.         else {
  150.             pushBack(cc);
  151.             token = nameconst;
  152.             }
  153.         }
  154.  
  155.     else if (isdigit(cc)) {        /* number */
  156.         longresult = cc - '0';
  157.         while (nextChar() && isdigit(cc)) {
  158.             *tp++ = cc;
  159.             longresult = (longresult * 10) + (cc - '0');
  160.             }
  161.         if (longCanBeInt(longresult)) {
  162.             tokenInteger = longresult;
  163.             token = intconst;
  164.             }
  165.         else {
  166.             token = floatconst;
  167.             tokenFloat = (double) longresult;
  168.             }
  169.         if (cc == '.') {    /* possible float */
  170.             if (nextChar() && isdigit(cc)) {
  171.                 *tp++ = '.';
  172.                 do
  173.                     *tp++ = cc;
  174.                 while (nextChar() && isdigit(cc));
  175.                 if (cc) pushBack(cc);
  176.                 token = floatconst;
  177.                 *tp = '\0';
  178.                 tokenFloat = atof(tokenString);
  179.                 }
  180.             else {
  181.                 /* nope, just an ordinary period */
  182.                 if (cc) pushBack(cc);
  183.                 pushBack('.');
  184.                 }
  185.             }
  186.         else
  187.             pushBack(cc);
  188.  
  189.         if (nextChar() && cc == 'e') {    /* possible float */
  190.             if (nextChar() && cc == '-') {
  191.                 sign = true;
  192.                 ignore nextChar();
  193.                 }
  194.             else
  195.                 sign = false;
  196.             if (cc && isdigit(cc)) { /* yep, its a float */
  197.                 *tp++ = 'e';
  198.                 if (sign) *tp++ = '-';
  199.                 while (cc && isdigit(cc)) {
  200.                     *tp++ = cc;
  201.                     ignore nextChar();
  202.                     }
  203.                 if (cc) pushBack(cc);
  204.                 *tp = '\0';
  205.                 token = floatconst;
  206.                 tokenFloat = atof(tokenString);
  207.                 }
  208.             else {    /* nope, wrong again */
  209.                 if (cc) pushBack(cc);
  210.                 if (sign) pushBack('-');
  211.                 pushBack('e');
  212.                 }
  213.             }
  214.             else
  215.                 if (cc) pushBack(cc);
  216.         }
  217.  
  218.     else if (cc == '$') {        /* character constant */
  219.         tokenInteger = (int) nextChar();
  220.         token = charconst;
  221.         }
  222.  
  223.     else if (cc == '#') {        /* symbol */
  224.         tp--;    /* erase pound sign */
  225.         if (nextChar() == '(')
  226.             token = arraybegin;
  227.         else {
  228.             pushBack(cc);
  229.             while (nextChar() && isSymbolChar(cc))
  230.                 *tp++ = cc;
  231.             pushBack(cc);
  232.             token = symconst;
  233.             }
  234.         }
  235.  
  236.     else if (cc == '\'') {        /* string constant */
  237.         tp--;    /* erase pound sign */
  238.         strloop:
  239.         while (nextChar() && (cc != '\''))
  240.             *tp++ = cc;
  241.         /* check for nested quote marks */
  242.         if (cc && nextChar() && (cc == '\'')) {
  243.             *tp++ = cc;
  244.             goto strloop;
  245.             }
  246.         pushBack(cc);
  247.         token = strconst;
  248.         }
  249.  
  250.     else if (isClosing(cc))        /* closing expressions */
  251.         token = closing;
  252.  
  253.     else if (singleBinary(cc)) {    /* single binary expressions */
  254.         token = binary;
  255.         }
  256.  
  257.     else {                /* anything else is binary */
  258.         if (nextChar() && binarySecond(cc))
  259.             *tp++ = cc;
  260.         else
  261.             pushBack(cc);
  262.         token = binary;
  263.         }
  264.  
  265.     *tp = '\0';
  266.     return(token);
  267. }
  268.  
  269.